<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>泉州拍照打卡</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
  <style>
    #map { height: 100vh; }
    .gallery-bubble {
      display: none;
      position: fixed;
      z-index: 1000;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      background: rgba(0, 0, 0, 0.6);
      padding: 24px;
      box-sizing: border-box;
      overflow: hidden;
      text-align: center;
    }

    .gallery-bubble::after, .gallery-arrow {
      content: "";
      position: absolute;
      bottom: -10px;
      left: 50%;
      transform: translateX(-50%);
      border-width: 10px 10px 0 10px;
      border-style: solid;
      border-color: white transparent transparent transparent;
      z-index: 1001;
    }

    #main-container {
      position: relative;
      display: flex;
      flex-direction: column;
      align-items: center;
    }

    .gallery-caption {
      width: 100%;
      padding: 12px 0;
      background: none;
      color: white;
      font-size: 17px;
      font-weight: 500;
      text-align: center;
    }

    #gallery-main {
      max-width: 80vw;
      max-height: 80vh;
      border-radius: 12px;
    }
    #close-gallery {
      position: absolute;
      top: 20px;
      right: 24px;
      background: rgba(255,255,255,0.8);
      border: none;
      font-size: 32px;
      cursor: pointer;
      border-radius: 6px;
      padding: 0 10px;
      line-height: 36px;
      height: 36px;
      box-shadow: 0 1px 4px rgba(0,0,0,0.2);
      z-index: 2000;
    }

    #thumbnails {
      margin-top: 10px;
      display: flex;
      overflow-x: auto;
      gap: 10px;
      justify-content: center;
    }

    #thumbnails img {
      height: 60px;
      cursor: pointer;
      border: 2px solid transparent;
      border-radius: 6px;
    }

    #thumbnails img.active {
      border-color: #007aff;
    }

    #prev-arrow, #next-arrow {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      font-size: 32px;
      padding: 8px 12px;
      border: none;
      border-radius: 50%;
      background-color: rgba(255,255,255,0.8);
      box-shadow: 0 2px 6px rgba(0,0,0,0.2);
      cursor: pointer;
    }
    #prev-arrow {
      left: 20px;
    }
    #next-arrow {
      right: 20px;
    }
  </style>
</head>
<body>
  <div id="map"></div>

  <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
  <script src="https://unpkg.com/leaflet.markercluster/dist/leaflet.markercluster.js"></script>
  <link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.css" />
  <link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.Default.css" />
  <script>
    const map = L.map('map').setView([35.6895, 139.6917], 5);

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '© OpenStreetMap contributors'
    }).addTo(map);

    const markers = L.markerClusterGroup({
      spiderfyOnMaxZoom: false,
      showCoverageOnHover: false,
      zoomToBoundsOnClick: false,
      iconCreateFunction: function (cluster) {
        const childMarkers = cluster.getAllChildMarkers();
        const firstImage = childMarkers.length > 0
          ? (childMarkers[0].getPopup().getContent().match(/<img src="([^"]+)"/) || [])[1]
          : null;

        if (childMarkers.length === 1) {
          return null;
        }

        return L.divIcon({
          html: firstImage
            ? `<div style="position: relative; width: 80px; height: 80px; overflow: visible; border: 2px solid white; box-shadow: 0 4px 12px rgba(0,0,0,0.2); border-radius: 12px;">
                <div style="width: 100%; height: 100%; overflow: hidden; border-radius: 12px;">
                  <img src="${firstImage}" style="width: 100%; height: 100%; object-fit: cover;">
                </div>
                <div style="position: absolute; bottom: 6px; left: 8px; color: white; font-size: 14px; font-weight: bold;">
                  ${childMarkers.length}
                </div>
                <div style="position: absolute; bottom: -10px; left: 50%; transform: translateX(-50%);
                            width: 0; height: 0; border-left: 8px solid transparent;
                            border-right: 8px solid transparent; border-top: 10px solid white;">
                </div>
              </div>`
            : `<div style="width: 80px; height: 80px; background: gray;"></div>`,
          className: '',
          iconSize: [80, 80]
        });
      }
    });

    markers.on('clusterclick', function (a) {
      const childMarkers = a.layer.getAllChildMarkers();
      const images = childMarkers.map(m => {
        const popupContent = m.getPopup().getContent();
        const match = popupContent.match(/<img src="([^"]+)"/);
        const captionMatch = popupContent.match(/<h3>(.*?)<\/h3>/);
        return match ? { src: match[1], caption: captionMatch ? captionMatch[1] : '' } : null;
      }).filter(Boolean);

      if (images.length > 0) {
        showImageGallery(images);
      }
    });

    fetch("all_image_positions.json")
      .then(res => res.json())
      .then(data => {
        data.forEach(item => {
          const popup = `
            <h3>${item.query}</h3>
            <img src="${item.image_path}" width="200">
          `;
          const icon = L.divIcon({
            html: `<div style="position: relative; width: 80px; height: 80px; overflow: visible; border: 2px solid white; box-shadow: 0 4px 12px rgba(0,0,0,0.2); border-radius: 12px;">
                     <div style="width: 100%; height: 100%; overflow: hidden; border-radius: 12px;">
                       <img src="${item.image_path}" style="width: 100%; height: 100%; object-fit: cover;">
                     </div>
                     <div style="position: absolute; bottom: -10px; left: 50%; transform: translateX(-50%);
                                 width: 0; height: 0; border-left: 8px solid transparent;
                                 border-right: 8px solid transparent; border-top: 10px solid white;">
                     </div>
                   </div>`,
            className: '',
            iconSize: [80, 80]
          });
          const marker = L.marker([item.lat, item.lng], { icon }); // 不再 .bindPopup(popup)
          marker.getPopup = () => ({ getContent: () => popup });  // 为 cluster 提供 getPopup() 伪接口
          marker.on('click', () => {
            map.setView([item.lat, item.lng], map.getZoom(), { animate: true });
            showImageGallery([{ src: item.image_path, caption: item.query }]);
          });
          markers.addLayer(marker);
        });
        setTimeout(() => {
          if (markers.getLayers().length > 0) {
            map.fitBounds(markers.getBounds());
          }
        }, 100);
        map.addLayer(markers);
      });
  </script>

  <div id="gallery-modal" class="gallery-bubble" style="position:fixed;">
    <button id="close-gallery" onclick="closeGallery()">×</button>
    <div id="caption" class="gallery-caption"></div>
    <div class="gallery-arrow"></div>
    <div id="main-container">
      <div id="main-image"><img src="" id="gallery-main"></div>
    </div>
    <button id="prev-arrow" onclick="prevImage()">❮</button>
    <button id="next-arrow" onclick="nextImage()">❯</button>
    <div id="thumbnails"></div>
  </div>
  <script>
    let galleryImages = [];
    let currentIndex = 0;

    function showImageGallery(imageObjs) {
      galleryImages = imageObjs;
      currentIndex = 0;
      updateGallery();
      document.getElementById('gallery-modal').style.display = 'block';
    }

    function updateGallery() {
      const current = galleryImages[currentIndex];
      document.getElementById('gallery-main').src = current.src;
      document.getElementById('caption').innerText = current.caption || '';
      const thumbs = document.getElementById('thumbnails');
      thumbs.innerHTML = galleryImages.map((img, i) =>
        `<img src="${img.src}" class="${i === currentIndex ? 'active' : ''}" onclick="goToImage(${i})">`
      ).join('');
    }

    function nextImage() {
      currentIndex = (currentIndex + 1) % galleryImages.length;
      updateGallery();
    }

    function prevImage() {
      currentIndex = (currentIndex - 1 + galleryImages.length) % galleryImages.length;
      updateGallery();
    }

    function goToImage(i) {
      currentIndex = i;
      updateGallery();
    }

    function closeGallery() {
      document.getElementById('gallery-modal').style.display = 'none';
    }
  </script>
</body>
</html>